"""
TODO 基本概念
1、索引：存储引擎用来快速查找记录的一种数据结构
        优点：可以加快数据的查询速度
        缺点：创建索引会浪费时间、占有磁盘空间，随数据量增多，耗费的时间会更多
2、分类
  ① 按实现方式：
        Hash索引
        B + Tree索引：一般就是用这个
  ② 按表列属性分为：
       单列索引
          普通索引：normal，没有什么限制，允许定义索引的列中插入重复值和空值
          唯一索引：索引列的值必须唯一，但允许有空值，如果是组合索引，列值的组合必须唯一
          主键索引：每张表一般有自己的主键，创建表时，MySQL会自动在主键列上建立一个索引，唯一性，不允许为NULL，是一种特殊的唯一索引
       组合索引：复合索引，将多个列组合起来创建索引，可以创建为普通索引，也可以为唯一索引
               使用复合最左原则
       全文索引：关键字fulltext，类似于搜索引擎，基于相似度的查询，和 like + % 模糊查询类似，但大量数据面前，全文索引效率高很多
               先建表，有数据的前提下，用create index 创建fulltext索引，效率更高
               MySQL5.6以前的版本，仅MylSAM存储引擎支持全文索引
               MySQL5.6以后的版本，仅MylSAM、InnoDB存储引擎支持全文索引
               只有字段的数据类型为char、varchar、text及其系列（即字符串类型）才可以建立全文索引
               两个变量：词的长度在 [最小搜索长度, 最大搜索长度] 区间，才能使用全文索引搜索
               查看这两个变量的默认值    select variables like '%ft%';
       空间索引：是对空间数据类型的字段建立的索引
               支持OpenGIS几何数据模型
               MySQL的空间数据类型：GEOMETRY - geometry（任何一种空间类型，可以表示点、线、多边形）
                                 POINT - point（点，坐标值）
                                 LINESTRING - linestring（线，由一系列点连接而成）
                                 POLYGON - polygon（多边形，由多条线组成）
注意：索引名不能重复
3、原则：
    更新频繁的列不设索引
    数据量小的表不使用索引
    重复数据多的字段不设索引（男、女，重复率 > 15%）
    优选考虑where 和 order by 涉及的列建立索引
4、create unique index index_f on student(phone_num,name);
  ① select * from student where name = '张三';
  ② select * from student where phone_num = '12345678999';
  ③ select * from student where phone_num = '12345678999' and name = '张三';
  ④ select * from student where name = '张三' and phone_num = '12345678999';
这里：满足复合索引最左原则的有②、③、④（③等同于④），①不满足。
TODO 添加索引
1、创建表时直接指定
     create table student (
        id int primary key,
        card_id varchar(20), -- 身份证号(每个人的身份证号是唯一的）
        name varchar(20),
        phone_num int,
        age int,
        content varchar(1000),
        geom_point geometry not null,   -- 经纬度
        shop_name varchar(64) not null comment 门店名称, -- comment 表示注释，等同于 --
        index index_n(name)                -- 普通索引
        unique index_c(card_id)            -- 唯一索引
        index index_f(name,age)            -- 复合普通索引
        unique index_f(card_id,phone_num)  -- 复合唯一索引
        fulltext(content)                  -- 全文索引
        spatial key geom_index(geom_point) -- 空间索引
     );
2、直接创建
     create index index_s on student(name);                       -- 普通索引
     create unique index index_c on student(card_id);             -- 唯一索引
     create index index_f on student(name,age);                   -- 复合普通索引
     create unique index index_f on student(card_id,phone_num);   -- 复合唯一索引
     create fulltext index full_index on student(content);        -- 全文索引
3、修改表结构（添加索引）
     alter table student add index index_s(name);                 -- 普通索引
     alter table student add unique index_c(card_id);             -- 唯一索引
     alter table student add index index_f(name,age);             -- 复合普通索引
     alter table student add unique index_f(card_id,phone_num);   -- 复合唯一索引
     alter table student add fulltext full_index(content);        -- 全文索引
 TODO 查看索引
1、查看数据库中所有索引
     select * from mysql.`innodb_index_stats` a where a.`database_name` = 'test1';
2、查看表中所有索引
     select * from mysql.`innodb_index_stats` a where a.`database_name` = 'test1' and a,table_name like '%student%';
     或：
     select index from student;
     或：
     show index from student;
3、全文索引的使用
     select * from student where match(content) against('yo');   -- 没有结果，单词数需要 >= 3
     select * from student where match(content) against('you');  -- 有结果
TODO 删除索引
1、drop index index_s on student;
2、alter table student drop index index_s;
TODO 内部原理
1、概述：索引本身很大，通常以索引文件的形式存储在磁盘上
       索引查找过程中要产生磁盘I/O消耗
       索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数
2、算法：
   ① Hash算法
       20 --> f(x) --> 0x11
       30 --> f(x) --> 0x12
       40 --> f(x) --> 0x13
         优点：通过字段的值计算的hash值，定位数据非常快
         缺点：不能进行范围查找，因为散列表中的值是无序的，无法进行大小的比较，有可能产生Hash冲突
   ② 二叉树
       特性：最多两个分支，分为左子树（根节点以下左边的分支）、右子树、根节点（分叉之前的那个点），左子树 < 根节点 < 右子树
       缺点：有可能给产生不平衡，类似于链表的结构
         （7比10小，去左边找，7比5大，去右边找）
   ③ 平衡二叉树
      特性：左子树和右子树都是平衡二叉树
           左子树 < 中间值 < 右子树
           左子树和右子树的深度之差的绝对值 <= 1
      缺点：插入操作需要旋转
           支持范围查询，但回旋查询效率较低，如要查询大于8的，会回旋到父节点7、10
           如果存放几百条数据的情况下，树高度越高，查询效率越慢（高度，数连接的线的条数）
   ④ BTREE树
TODO 综合案例
临时表：当前会话结束后，表会自动删除
   create temporary table tmp
   as
 -- 将表分为三个子表，进行自关联查询
   select t3.id as id_3,       -- 3级分类id
          t3.name as name_3,   -- 3级分类名称
          t2.id as id_2,       -- 2级分类id
          t2.name as name_2,   -- 2级分类名称
          t1.id as id_1,       -- 1级分类id
          t1.name as name_1,   -- 1级分类名称
   from test1.student t3,
        test1.student t2,
        test1.student t1,
   where t3.pid = t2.id
     and t2.pid = t1.id;

create table test(title varchar(20));
set profiling=1;  (开启时间检测）
alter table test add index(title);
select * from test where title='ha-9999';
show profiling;(查看执行时间）
"""